package cn.jn.lhm.netty.part08.chat.core;

import cn.jn.lhm.netty.part08.chat.handler.ClientInitHandler;
import cn.jn.lhm.netty.part08.chat.handler.ClientLoginHandler;
import cn.jn.lhm.netty.part08.chat.handler.ClientQuitHandler;
import cn.jn.lhm.netty.part08.chat.message.PingMessage;
import cn.jn.lhm.netty.part08.chat.protocol.ScopeMessageCodec;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;

import static cn.jn.lhm.netty.part08.chat.core.ChatServer.LOGGING_HANDLER;

/**
 * @author lhm 2753914576@qq.com
 * @time 2023/10/31 - 23:19
 **/
@Slf4j
public class ChatClient {

    public static void main(String[] args) {
        NioEventLoopGroup worker = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(worker);
            bootstrap.channel(NioSocketChannel.class);
            bootstrap.handler(new ChannelInitializer<NioSocketChannel>() {
                @Override
                protected void initChannel(NioSocketChannel ch) throws Exception {
                    //ch.pipeline().addLast(new ProtocolFrameDecoder());
                    ch.pipeline().addLast(new ScopeMessageCodec());
                    // 当处于写空闲的时候回触发 {@code IdleState#WRITER_IDLE} 事件
                    ch.pipeline().addLast(new IdleStateHandler(0, 3, 0));
                    ch.pipeline().addLast(new ChannelDuplexHandler() {
                        @Override
                        public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
                            if (evt instanceof IdleStateEvent de) {
                                if (de.state() == IdleState.WRITER_IDLE) {
                                    ctx.writeAndFlush(new PingMessage());
                                }
                            }
                        }
                    });
                    ch.pipeline().addLast(LOGGING_HANDLER);
                    // 登录处理器,负责处理客户端的账号输入
                    ch.pipeline().addLast(new ClientLoginHandler());
                    // 处理用户名密码校验
                    ch.pipeline().addLast(new ClientInitHandler());
                    ch.pipeline().addLast(new ClientQuitHandler());
                }
            });
            ChannelFuture future = bootstrap.connect("localhost", 8080);
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            log.error("client error...", e);
        } finally {
            worker.shutdownGracefully();
        }
    }
}
